package com.example.a_java.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.a_java.entity.LoanContract;
import com.example.a_java.entity.RepaymentInstallment;
import com.example.a_java.entity.RepaymentPlan;
import com.example.a_java.mapper.LoanContractMapper;
import com.example.a_java.mapper.RepaymentPlanMapper;
import com.example.a_java.service.RepaymentInstallmentService;
import com.example.a_java.service.RepaymentPlanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 还款计划Service实现类
 */
@Slf4j
@Service
public class RepaymentPlanServiceImpl extends ServiceImpl<RepaymentPlanMapper, RepaymentPlan> implements RepaymentPlanService {

    @Autowired
    private RepaymentPlanMapper repaymentPlanMapper;

    @Autowired
    private RepaymentInstallmentService repaymentInstallmentService;

    @Autowired
    private LoanContractMapper loanContractMapper;

    @Override
    public Page<RepaymentPlan> getRepaymentPlanPage(int pageNum, int pageSize, String contractNo, String loanNo,
                                                  String customerName, Integer repayStatus, String repayMethod,
                                                  String startDate, String endDate) {
        Page<RepaymentPlan> page = new Page<>(pageNum, pageSize);
        return repaymentPlanMapper.selectPlanPage(page, contractNo, loanNo, customerName, repayStatus, repayMethod, startDate, endDate);
    }

    @Override
    public Map<String, Object> getRepaymentPlanDetail(Long planId) {
        // 获取还款计划详情
        RepaymentPlan plan = this.getById(planId);
        if (plan == null) {
            throw new RuntimeException("还款计划不存在");
        }

        // 获取分期明细
        List<RepaymentInstallment> installments = repaymentInstallmentService.getInstallmentsByPlanId(planId);
        
        // 获取已还记录（可从分期明细中过滤已还款的记录）
        List<Map<String, Object>> payRecords = installments.stream()
                .filter(item -> "paid".equals(item.getStatus()))
                .map(item -> {
                    Map<String, Object> record = new HashMap<>();
                    record.put("id", item.getId());
                    record.put("installmentId", item.getId());
                    record.put("payDate", item.getPayDate());
                    record.put("payAmount", item.getPayAmount());
                    record.put("principal", item.getPrincipal());
                    record.put("interest", item.getInterest());
                    record.put("penalty", item.getPenalty());
                    return record;
                })
                .collect(Collectors.toList());

        Map<String, Object> result = new HashMap<>();
        result.put("id", plan.getId());
        result.put("contractId", plan.getContractId());
        result.put("contractNo", plan.getContractNo());
        result.put("loanNo", plan.getLoanNo());
        result.put("customerName", plan.getCustomerName());
        result.put("loanAmount", plan.getLoanAmount());
        result.put("loanTerm", plan.getLoanTerm());
        result.put("interestRate", plan.getInterestRate());
        result.put("repaymentMethod", plan.getRepaymentMethod());
        result.put("startDate", plan.getStartDate());
        result.put("endDate", plan.getEndDate());
        result.put("totalPeriods", plan.getTotalPeriods());
        result.put("paidPeriods", plan.getPaidPeriods());
        result.put("totalAmount", plan.getTotalAmount());
        result.put("paidAmount", plan.getPaidAmount());
        result.put("remainingAmount", plan.getRemainingAmount());
        result.put("status", plan.getStatus());
        result.put("statusName", getStatusName(plan.getStatus()));
        result.put("installments", installments);
        result.put("payRecords", payRecords);

        return result;
    }

    @Override
    public Map<String, Object> getRepaymentPlanByLoanNo(String loanNo) {
        // 根据贷款编号查询还款计划
        RepaymentPlan plan = repaymentPlanMapper.selectByLoanNo(loanNo);
        if (plan == null) {
            throw new RuntimeException("还款计划不存在");
        }

        // 获取分期明细
        List<RepaymentInstallment> installments = repaymentInstallmentService.getInstallmentsByPlanId(plan.getId());

        Map<String, Object> result = new HashMap<>();
        result.put("contractId", plan.getContractId());
        result.put("contractNo", plan.getContractNo());
        result.put("loanNo", plan.getLoanNo());
        result.put("customerName", plan.getCustomerName());
        result.put("loanAmount", plan.getLoanAmount());
        result.put("term", plan.getLoanTerm());
        result.put("interestRate", plan.getInterestRate());
        result.put("repayMethod", plan.getRepaymentMethod());
        result.put("totalInterest", plan.getTotalInterest());
        result.put("totalAmount", plan.getTotalAmount());
        result.put("startDate", plan.getStartDate());
        result.put("endDate", plan.getEndDate());
        result.put("plans", installments);

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> generateRepaymentPlan(Long contractId) {
        // 检查合同是否存在
        LoanContract contract = loanContractMapper.selectById(contractId);
        if (contract == null) {
            throw new RuntimeException("合同不存在，合同ID: " + contractId);
        }

        // 检查是否已存在还款计划
        LambdaQueryWrapper<RepaymentPlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RepaymentPlan::getContractId, contractId);
        if (this.count(wrapper) > 0) {
            throw new RuntimeException("该合同已生成还款计划，不能重复生成");
        }

        // 创建还款计划
        RepaymentPlan plan = new RepaymentPlan();
        plan.setContractId(contract.getContractId());
        plan.setContractNo(contract.getContractNo());
        plan.setLoanId(contract.getApplyId());
        plan.setLoanNo("DK" + contract.getContractNo().substring(2)); // 简单处理，使用合同编号生成贷款编号
        plan.setCustomerId(contract.getCustId());
        plan.setCustomerName("客户" + contract.getCustId()); // 这里应该从客户信息表查询
        
        plan.setLoanAmount(contract.getLoanAmount());
        plan.setLoanTerm(contract.getLoanTerm());
        plan.setInterestRate(contract.getInterestRate());
        
        // 根据合同中的还款方式代码获取还款方式名称
        String repaymentMethod;
        switch (contract.getRepayMethod()) {
            case 1:
                repaymentMethod = "等额本息";
                break;
            case 2:
                repaymentMethod = "等额本金";
                break;
            case 3:
                repaymentMethod = "先息后本";
                break;
            case 4:
                repaymentMethod = "到期一次性还本付息";
                break;
            default:
                repaymentMethod = "自定义";
        }
        plan.setRepaymentMethod(repaymentMethod);
        
        plan.setStartDate(contract.getStartDate());
        plan.setEndDate(contract.getEndDate());
        plan.setTotalPeriods(contract.getLoanTerm());
        plan.setPaidPeriods(0);
        
        // 计算总利息和总金额（根据实际情况，这里使用一个简单的公式）
        BigDecimal totalInterest = calculateTotalInterest(contract.getLoanAmount(), contract.getInterestRate(), 
                                                        contract.getLoanTerm(), repaymentMethod);
        plan.setTotalInterest(totalInterest);
        plan.setTotalAmount(contract.getLoanAmount().add(totalInterest));
        
        plan.setPaidAmount(BigDecimal.ZERO);
        plan.setRemainingAmount(plan.getTotalAmount());
        plan.setStatus(1); // 正常
        plan.setCreateBy("system");
        
        // 保存还款计划
        this.save(plan);
        
        // 生成分期明细
        boolean success = repaymentInstallmentService.generateInstallments(
                plan.getId(), 
                contract.getLoanAmount(), 
                contract.getInterestRate(),
                contract.getLoanTerm(),
                repaymentMethod,
                contract.getStartDate()
        );
        
        if (!success) {
            throw new RuntimeException("生成分期明细失败");
        }
        
        // 获取第一期还款日期和金额，更新计划的下次还款信息
        RepaymentInstallment nextInstallment = repaymentInstallmentService.getOne(
                new LambdaQueryWrapper<RepaymentInstallment>()
                        .eq(RepaymentInstallment::getPlanId, plan.getId())
                        .eq(RepaymentInstallment::getStatus, "pending")
                        .orderByAsc(RepaymentInstallment::getPeriod)
                        .last("LIMIT 1")
        );
        
        if (nextInstallment != null) {
            plan.setNextRepayDate(nextInstallment.getDueDate());
            plan.setNextRepayAmount(nextInstallment.getAmount());
            this.updateById(plan);
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("planId", plan.getId());
        result.put("planCount", plan.getTotalPeriods());
        result.put("totalPrincipal", plan.getLoanAmount());
        result.put("totalInterest", plan.getTotalInterest());
        result.put("totalAmount", plan.getTotalAmount());
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> batchGenerateRepaymentPlan(List<Long> contractIds) {
        int successCount = 0;
        int failCount = 0;
        List<Map<String, Object>> details = new ArrayList<>();
        
        for (Long contractId : contractIds) {
            try {
                Map<String, Object> result = generateRepaymentPlan(contractId);
                
                Map<String, Object> detail = new HashMap<>();
                detail.put("contractId", contractId);
                detail.put("contractNo", result.get("contractNo"));
                detail.put("planCount", result.get("planCount"));
                detail.put("success", true);
                details.add(detail);
                
                successCount++;
            } catch (Exception e) {
                log.error("生成还款计划失败，合同ID: " + contractId, e);
                
                // 查询合同编号
                LoanContract contract = loanContractMapper.selectById(contractId);
                String contractNo = contract != null ? contract.getContractNo() : "未知";
                
                Map<String, Object> detail = new HashMap<>();
                detail.put("contractId", contractId);
                detail.put("contractNo", contractNo);
                detail.put("planCount", 0);
                detail.put("success", false);
                detail.put("failReason", e.getMessage());
                details.add(detail);
                
                failCount++;
            }
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("successCount", successCount);
        result.put("failCount", failCount);
        result.put("details", details);
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> adjustRepaymentPlan(Long planId, List<Map<String, Object>> adjustments, String reason, List<String> attachmentUrls) {
        // 检查还款计划是否存在
        RepaymentPlan plan = this.getById(planId);
        if (plan == null) {
            throw new RuntimeException("还款计划不存在");
        }
        
        // 检查调整明细非空
        if (adjustments == null || adjustments.isEmpty()) {
            throw new RuntimeException("调整明细不能为空");
        }
        
        // 对每个调整的分期进行处理
        for (Map<String, Object> adjustment : adjustments) {
            Long installmentId = Long.valueOf(adjustment.get("installmentId").toString());
            RepaymentInstallment installment = repaymentInstallmentService.getById(installmentId);
            
            if (installment == null) {
                throw new RuntimeException("分期明细不存在，ID: " + installmentId);
            }
            
            // 已还款的分期不能调整
            if ("paid".equals(installment.getStatus())) {
                throw new RuntimeException("已还款的分期不能调整，期数: " + installment.getPeriod());
            }
            
            // 更新分期明细
            LocalDate dueDate = LocalDate.parse(adjustment.get("dueDate").toString());
            BigDecimal principal = new BigDecimal(adjustment.get("principal").toString());
            BigDecimal interest = new BigDecimal(adjustment.get("interest").toString());
            
            installment.setDueDate(dueDate);
            installment.setPrincipal(principal);
            installment.setInterest(interest);
            installment.setAmount(principal.add(interest));
            
            // 更新时间
            repaymentInstallmentService.updateById(installment);
        }
        
        // 记录计划调整的有效日期（当前日期）
        LocalDate effectiveDate = LocalDate.now();
        
        // 更新还款计划的其他信息...
        
        Map<String, Object> result = new HashMap<>();
        result.put("adjustId", 1L); // 这里假设是某个调整记录的ID
        result.put("effectiveDate", effectiveDate);
        
        return result;
    }

    @Override
    public Map<String, Object> calculatePenalty(Long installmentId, Integer overdueDays) {
        return repaymentInstallmentService.calculatePenalty(installmentId, overdueDays);
    }

    @Override
    public Map<String, Object> getStatistics() {
        return repaymentPlanMapper.getStatistics();
    }

    @Override
    public List<Map<String, Object>> getLoanNumbers(String keyword, Integer status) {
        // 这里实现根据关键字和状态查询贷款编号的逻辑
        List<Map<String, Object>> result = new ArrayList<>();
        
        // 示例数据
        if (keyword == null || keyword.isEmpty() || "DK".contains(keyword.toUpperCase())) {
            Map<String, Object> item1 = new HashMap<>();
            item1.put("id", 1);
            item1.put("loanNo", "DK202403010001");
            item1.put("customerName", "张三");
            item1.put("loanAmount", new BigDecimal("100000.00"));
            result.add(item1);
        }
        
        if (keyword == null || keyword.isEmpty() || "DK".contains(keyword.toUpperCase())) {
            Map<String, Object> item2 = new HashMap<>();
            item2.put("id", 2);
            item2.put("loanNo", "DK202403020001");
            item2.put("customerName", "李四");
            item2.put("loanAmount", new BigDecimal("200000.00"));
            result.add(item2);
        }
        
        return result;
    }

    @Override
    public List<Map<String, Object>> getCustomerNames(String keyword) {
        // 这里实现根据关键字查询客户名称的逻辑
        List<Map<String, Object>> result = new ArrayList<>();
        
        // 示例数据
        if (keyword == null || keyword.isEmpty() || "张".contains(keyword)) {
            Map<String, Object> item1 = new HashMap<>();
            item1.put("id", 1);
            item1.put("customerName", "张三");
            item1.put("phone", "13800138000");
            item1.put("idCard", "110101199001011234");
            result.add(item1);
        }
        
        if (keyword == null || keyword.isEmpty() || "李".contains(keyword)) {
            Map<String, Object> item2 = new HashMap<>();
            item2.put("id", 2);
            item2.put("customerName", "李四");
            item2.put("phone", "13900139000");
            item2.put("idCard", "110101199101011234");
            result.add(item2);
        }
        
        return result;
    }

    @Override
    public List<Map<String, Object>> getRepaymentStatuses() {
        List<Map<String, Object>> statuses = new ArrayList<>();
        
        Map<String, Object> status1 = new HashMap<>();
        status1.put("value", 1);
        status1.put("label", "待还款");
        statuses.add(status1);
        
        Map<String, Object> status2 = new HashMap<>();
        status2.put("value", 2);
        status2.put("label", "已还款");
        statuses.add(status2);
        
        Map<String, Object> status3 = new HashMap<>();
        status3.put("value", 3);
        status3.put("label", "逾期");
        statuses.add(status3);
        
        return statuses;
    }

    @Override
    public List<Map<String, Object>> getPaymentMethods() {
        List<Map<String, Object>> methods = new ArrayList<>();
        
        Map<String, Object> method1 = new HashMap<>();
        method1.put("value", "bank_transfer");
        method1.put("label", "银行转账");
        methods.add(method1);
        
        Map<String, Object> method2 = new HashMap<>();
        method2.put("value", "cash");
        method2.put("label", "现金");
        methods.add(method2);
        
        Map<String, Object> method3 = new HashMap<>();
        method3.put("value", "alipay");
        method3.put("label", "支付宝");
        methods.add(method3);
        
        Map<String, Object> method4 = new HashMap<>();
        method4.put("value", "wechat");
        method4.put("label", "微信");
        methods.add(method4);
        
        return methods;
    }

    /**
     * 根据状态代码获取状态名称
     */
    private String getStatusName(Integer status) {
        switch (status) {
            case 1:
                return "正常";
            case 2:
                return "结清";
            case 3:
                return "逾期";
            default:
                return "未知";
        }
    }

    /**
     * 计算总利息
     */
    private BigDecimal calculateTotalInterest(BigDecimal principal, BigDecimal yearRate, Integer term, String repaymentMethod) {
        // 月利率
        BigDecimal monthRate = yearRate.divide(new BigDecimal("100"), 10, RoundingMode.HALF_UP)
                                    .divide(new BigDecimal("12"), 10, RoundingMode.HALF_UP);
        
        BigDecimal totalInterest;
        
        if ("等额本息".equals(repaymentMethod)) {
            // 等额本息：每月还款金额 = P × [i × (1 + i)^n] ÷ [(1 + i)^n - 1]
            BigDecimal powN = BigDecimal.ONE.add(monthRate).pow(term);
            BigDecimal monthlyPayment = principal.multiply(monthRate.multiply(powN))
                                              .divide(powN.subtract(BigDecimal.ONE), 10, RoundingMode.HALF_UP);
            
            // 总利息 = 还款总额 - 本金
            totalInterest = monthlyPayment.multiply(new BigDecimal(term)).subtract(principal);
        } else if ("等额本金".equals(repaymentMethod)) {
            // 等额本金：总利息 = (本金/期数 + 本金) * 期数 * 月利率 / 2
            totalInterest = principal.multiply(new BigDecimal(term + 1))
                                  .multiply(monthRate)
                                  .divide(new BigDecimal("2"), 10, RoundingMode.HALF_UP);
        } else if ("先息后本".equals(repaymentMethod)) {
            // 先息后本：总利息 = 本金 * 月利率 * 期数
            totalInterest = principal.multiply(monthRate).multiply(new BigDecimal(term));
        } else if ("到期一次性还本付息".equals(repaymentMethod)) {
            // 到期一次性还本付息：总利息 = 本金 * 月利率 * 期数
            totalInterest = principal.multiply(monthRate).multiply(new BigDecimal(term));
        } else {
            // 默认按等额本息计算
            BigDecimal powN = BigDecimal.ONE.add(monthRate).pow(term);
            BigDecimal monthlyPayment = principal.multiply(monthRate.multiply(powN))
                                              .divide(powN.subtract(BigDecimal.ONE), 10, RoundingMode.HALF_UP);
            
            totalInterest = monthlyPayment.multiply(new BigDecimal(term)).subtract(principal);
        }
        
        return totalInterest.setScale(2, RoundingMode.HALF_UP);
    }
} 